//
// Created by Administrator on 2022/1/17.
//

#include "Torus.h"

Torus::Torus()
    : precision(48),
      inner(0.5f),
      outer(2.0f)
{
    Init();
}

Torus::Torus(float innerRadius, float outerRadius, int precision)
    : precision(precision),
      inner(innerRadius),
      outer(outerRadius)
{
    Init();
}

void Torus::Init()
{
    numVertices = (precision + 1) * (precision + 1);
    numIndices = precision * precision * 6;

    // indices先填充了，因为它构建的时候不是按顺序的
    for(int i = 0; i < numIndices; ++i)
    {
        indices.emplace_back(0);
    }

    // 计算第一个环
    float delta = PI_2 / float(precision);
    for(int i = 0; i <= precision; ++i)
    {
        float amt = float(i) * delta;
        // (x-y平面)绕z轴旋转点，然后将它往外移动
        glm::mat4 rMat = glm::rotate(glm::mat4(1.0f), amt, glm::vec3(0.0f, 0.0f, 1.0f));
        glm::vec3 initPos(rMat * glm::vec4(0.0f, outer, 0.0f, 1.0f));
        vertices.emplace_back(initPos + glm::vec3(inner, 0.0f, 0.0f));
        // 计算uv
        uvs.emplace_back(glm::vec2(0.0f, float(i) / float(precision)));
        // 计算切线和副切线，然后通过叉乘得到法线
        rMat = glm::rotate(glm::mat4(1.0f), amt + PI_OVER_2, glm::vec3(0.0f, 0.0f, 1.0f));
        tTangents.emplace_back(glm::vec3(rMat * glm::vec4(0.0f, -1.0f, 0.0f, 1.0f)));
        sTangents.emplace_back(glm::vec3(0.0f, 0.0f, -1.0f));
        normals.emplace_back(glm::cross(tTangents[i], sTangents[i]));
    }

    // 绕y轴旋转第一个环得到其他环
    for(int ring = 1; ring <= precision; ++ring)
    {
        for(int vert = 0; vert <= precision; ++vert)
        {
            // 绕y轴旋转初始环的顶点位置
            float amt = float(ring) * delta;
            glm::mat4 rMat = glm::rotate(glm::mat4(1.0f), amt, glm::vec3(0.0f, 1.0f, 0.0f));
            vertices.emplace_back(glm::vec3(rMat * glm::vec4(vertices[vert], 1.0f)));

            // 计算uv
            uvs.emplace_back(glm::vec2(float(ring) * 2.0f / float(precision), uvs[vert].t));

            // 绕y轴旋转切线和副切线
            rMat = glm::rotate(glm::mat4(1.0f), amt, glm::vec3(0.0f, 1.0f, 0.0f));
            sTangents.emplace_back(glm::vec3(rMat * glm::vec4(sTangents[vert], 1.0f)));
            rMat = glm::rotate(glm::mat4(1.0f), amt, glm::vec3(0.0f, 1.0f, 0.0f));
            tTangents.emplace_back(glm::vec3(rMat * glm::vec4(tTangents[vert], 1.0f)));

            // 绕y轴旋转法线
            rMat = glm::rotate(glm::mat4(1.0f), amt, glm::vec3(0.0f, 1.0f, 0.0f));
            normals.emplace_back(glm::vec3(rMat * glm::vec4(normals[vert], 1.0f)));
        }
    }

    // 计算索引
    int n = precision + 1;
    for(int ring = 0; ring < precision; ++ring)
    {
        for(int vert = 0; vert < precision; ++vert)
        {
            indices[(ring * precision + vert) * 2 * 3 + 0] = ring * n + vert;
            indices[(ring * precision + vert) * 2 * 3 + 1] = (ring + 1) * n + vert;
            indices[(ring * precision + vert) * 2 * 3 + 2] = ring * n + vert + 1;
            indices[((ring * precision + vert) * 2 + 1) * 3 + 0] = ring * n + vert + 1;
            indices[((ring * precision + vert) * 2 + 1) * 3 + 1] = (ring + 1) * n + vert;
            indices[((ring * precision + vert) * 2 + 1) * 3 + 2] = (ring + 1) * n + vert + 1;
        }
    }
}